#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <opencv2/opencv.hpp>
#include <vector>


int main() {

    const char* SERVER_IP = "192.168.0.2";
    const int SERVER_PORT = 5005;
    const int BUFFER_SIZE = 1440;


    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::cerr << "Error creating socket!" << std::endl;
        return 1;
    }

    struct sockaddr_in server_addr;
    std::memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        std::cerr << "Bind failed!" << std::endl;
	    std::cerr << "Bind failed! Error: " << strerror(errno) << std::endl;
        close(sockfd);
        return 1;
    }

    char buffer[BUFFER_SIZE];
    std::vector<uchar> image_data;
    ssize_t bytes_received;
    struct sockaddr_in client_addr;
    socklen_t addr_len = sizeof(client_addr);

    while (true) {

        bytes_received = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &addr_len);
        if (bytes_received < 0) {
            std::cerr << "Error: Receiving data failed" << std::endl;
            break;
        }

        std::cout << "Received packet of size: " << bytes_received << " bytes" << std::endl;

        image_data.insert(image_data.end(), buffer, buffer + bytes_received);

        if (image_data.size() >= 2 && image_data[image_data.size() - 2] == 0xFF && image_data[image_data.size() - 1] == 0xD9) {
            std::cout << "Complete image received. Decoding..." << std::endl;

            cv::Mat img = cv::imdecode(image_data, cv::IMREAD_COLOR);

            if (!img.empty()) {
                cv::imshow("Received Image", img);
                cv::waitKey(1);
            } else {
                std::cerr << "Error: Failed to decode image" << std::endl;
            }

            image_data.clear();
        }
    }

    close(sockfd);
    cv::destroyAllWindows();

    return 0;

}
